from rest_framework import viewsets, permissions, status
from rest_framework.response import Response
from rest_framework.decorators import action, api_view, permission_classes
from ..models import User
from ..serializers.user_serializer import UserSerializer, UserListSerializer
import pandas as pd
from io import BytesIO
from django.http import HttpResponse
import logging

logger = logging.getLogger(__name__)

# 添加一个简单的测试API，无需认证
@api_view(['GET'])
@permission_classes([])
def test_api_endpoint(request):
    """
    一个简单的测试API端点，用于验证API路由是否正常工作
    """
    # 获取分页参数
    page = int(request.query_params.get('page', 1))
    limit = int(request.query_params.get('limit', 10))
    
    # 创建测试数据
    test_data = [
        {'id': 1, 'username': 'admin', 'nickname': '管理员', 'email': 'admin@example.com', 'phone_number': '13800138000', 'role': 1, 'role_display': '管理员'},
        {'id': 2, 'username': 'user1', 'nickname': '客服1', 'email': 'user1@example.com', 'phone_number': '13900139000', 'role': 0, 'role_display': '普通客服'},
        {'id': 3, 'username': 'user2', 'nickname': '客服2', 'email': 'user2@example.com', 'phone_number': '13700137000', 'role': 0, 'role_display': '普通客服'},
        {'id': 4, 'username': 'user3', 'nickname': '客服3', 'email': 'user3@example.com', 'phone_number': '13600136000', 'role': 0, 'role_display': '普通客服'},
        {'id': 5, 'username': 'manager', 'nickname': '经理', 'email': 'manager@example.com', 'phone_number': '13500135000', 'role': 1, 'role_display': '管理员'}
    ]
    
    # 计算分页
    start = (page - 1) * limit
    end = min(start + limit, len(test_data))
    paginated_data = test_data[start:end]
    
    return Response({
        'code': 200,
        'message': 'API测试成功',
        'data': {
            'total': len(test_data),
            'items': paginated_data
        }
    })

class UserViewSet(viewsets.ModelViewSet):
    """
    用户视图集，提供用户的 list, create, retrieve, update, destroy 操作
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]
    
    def get_serializer_class(self):
        """
        根据操作类型选择序列化器
        """
        if self.action == 'list' or self.action == 'service_staff':
            return UserListSerializer
        return UserSerializer
    
    def get_permissions(self):
        """
        根据操作类型选择权限类
        """
        # 这些接口不需要认证，方便前端开发调试
        if self.action in ['list', 'service_staff', 'export_users', 'batch_delete', 'retrieve', 'import_data', 'import_template']:
            return []
        return [permission() for permission in self.permission_classes]
    
    def list(self, request, *args, **kwargs):
        """
        获取用户列表
        """
        try:
            logger.info(f"获取用户列表请求 - 参数: {request.query_params}")
            
            # 获取查询参数
            username = request.query_params.get('username', None)
            email = request.query_params.get('email', None)
            nickname = request.query_params.get('nickname', None)
            role = request.query_params.get('role', None)
            phone_number = request.query_params.get('phone_number', None)
            
            queryset = self.get_queryset()
            logger.info(f"初始查询集包含 {queryset.count()} 条记录")
            
            # 应用过滤条件
            if username:
                queryset = queryset.filter(username__icontains=username)
            if email:
                queryset = queryset.filter(email__icontains=email)
            if nickname:
                queryset = queryset.filter(nickname__icontains=nickname)
            if role is not None and role != '':
                queryset = queryset.filter(role=role)
            if phone_number:
                queryset = queryset.filter(phone_number__icontains=phone_number)
            
            logger.info(f"过滤后查询集包含 {queryset.count()} 条记录")
            
            # 获取分页参数
            page_num = request.query_params.get('page', 1)
            page_size = request.query_params.get('limit', 10)
            
            try:
                page_num = int(page_num)
                page_size = int(page_size)
            except (ValueError, TypeError):
                page_num = 1
                page_size = 10
            
            logger.info(f"分页参数: page={page_num}, limit={page_size}")
            
            # 计算分页
            start = (page_num - 1) * page_size
            end = page_num * page_size
            
            # 获取总记录数
            total = queryset.count()
            
            # 获取分页数据
            queryset = queryset[start:end]
            
            # 序列化数据
            serializer = self.get_serializer(queryset, many=True)
            
            logger.info(f"返回 {len(serializer.data)} 条记录，总记录数: {total}")
            
            # 返回结果
            return Response({
                'code': 200,
                'message': '获取用户列表成功',
                'data': {
                    'total': total,
                    'items': serializer.data
                }
            })
        except Exception as e:
            logger.exception(f"获取用户列表异常: {str(e)}")
            return Response({
                'code': 500,
                'message': f'获取用户列表失败: {str(e)}',
                'data': None
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def retrieve(self, request, *args, **kwargs):
        """
        获取单个用户详情
        """
        try:
            instance = self.get_object()
            serializer = self.get_serializer(instance)
            return Response({
                'code': 200,
                'message': '获取用户详情成功',
                'data': serializer.data
            })
        except Exception as e:
            logger.exception(f"获取用户详情异常: {str(e)}")
            return Response({
                'code': 500,
                'message': f'获取用户详情失败: {str(e)}',
                'data': None
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def create(self, request, *args, **kwargs):
        """
        创建用户
        """
        try:
            logger.info(f"创建用户请求 - 数据: {request.data}")
            serializer = self.get_serializer(data=request.data)
            
            if not serializer.is_valid():
                logger.error(f"创建用户验证失败 - 错误: {serializer.errors}")
                return Response({
                    'code': 400,
                    'message': '数据验证失败',
                    'errors': serializer.errors
                }, status=status.HTTP_400_BAD_REQUEST)
                
            self.perform_create(serializer)
            headers = self.get_success_headers(serializer.data)
            
            logger.info(f"用户创建成功 - ID: {serializer.data.get('id')}")
            
            return Response({
                'code': 201,
                'message': '创建用户成功',
                'data': serializer.data
            }, status=201, headers=headers)
        except Exception as e:
            logger.exception(f"创建用户异常: {str(e)}")
            return Response({
                'code': 500,
                'message': f'创建用户失败: {str(e)}',
                'data': None
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def update(self, request, *args, **kwargs):
        """
        更新用户
        """
        try:
            # 记录请求数据用于调试
            logger.info(f"更新用户请求 - ID: {kwargs.get('pk')}, 数据: {request.data}")
            
            partial = kwargs.pop('partial', False)
            instance = self.get_object()
            
            logger.info(f"更新用户 - 找到实例: {instance.id}, {instance.username}")
            
            # 处理密码字段
            data_to_update = request.data.copy()
            
            # 如果请求数据中包含pwd字段且不为空，使用它更新密码
            # 否则不更新密码字段
            if 'pwd' not in data_to_update or not data_to_update['pwd']:
                if 'pwd' in data_to_update:
                    del data_to_update['pwd']  # 删除空密码字段
            
            # 特殊处理可能存在的嵌套外键关系
            serializer = self.get_serializer(instance, data=data_to_update, partial=partial)
            
            # 验证数据
            if not serializer.is_valid():
                logger.error(f"更新用户验证失败 - 错误: {serializer.errors}")
                
                # 返回更详细的错误信息
                error_details = {}
                for field, errors in serializer.errors.items():
                    error_details[field] = [str(error) for error in errors]
                
                return Response({
                    'code': 400,
                    'message': '数据验证失败',
                    'errors': error_details
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 保存实例
            self.perform_update(serializer)
            logger.info(f"用户更新成功 - ID: {instance.id}")
            
            # 返回成功响应
            return Response({
                'code': 200,
                'message': '更新用户成功',
                'data': serializer.data
            })
        except Exception as e:
            logger.exception(f"更新用户异常 - {str(e)}")
            return Response({
                'code': 500,
                'message': f'更新用户失败: {str(e)}',
                'data': None
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def destroy(self, request, *args, **kwargs):
        """
        删除用户
        """
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response({
            'code': 204,
            'message': '删除用户成功'
        }, status=204)

    @action(detail=False, methods=['get'], url_path='profile')
    def get_profile(self, request):
        """
        获取当前登录用户的个人资料
        """
        try:
            user = User.objects.get(id=request.user.id)
            serializer = self.get_serializer(user)
            return Response({
                'code': 200,
                'message': '获取个人资料成功',
                'data': serializer.data
            })
        except Exception as e:
            return Response({
                'code': 500,
                'message': f'获取个人资料失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=False, methods=['put'], url_path='profile')
    def update_profile(self, request):
        """
        更新当前登录用户的个人资料
        """
        try:
            user = User.objects.get(id=request.user.id)
            
            # 仅允许修改特定字段
            allowed_fields = ['nickname', 'email', 'phone_number']
            update_data = {}
            
            for field in allowed_fields:
                if field in request.data:
                    update_data[field] = request.data[field]
            
            serializer = self.get_serializer(user, data=update_data, partial=True)
            if serializer.is_valid():
                serializer.save()
                return Response({
                    'code': 200,
                    'message': '个人资料更新成功',
                    'data': serializer.data
                })
            else:
                return Response({
                    'code': 400,
                    'message': '数据验证失败',
                    'errors': serializer.errors
                }, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            return Response({
                'code': 500,
                'message': f'更新个人资料失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=False, methods=['put'], url_path='password')
    def change_password(self, request):
        """
        修改当前登录用户的密码
        """
        try:
            user = User.objects.get(id=request.user.id)
            old_password = request.data.get('old_password')
            new_password = request.data.get('new_password')
            
            if not old_password or not new_password:
                return Response({
                    'code': 400,
                    'message': '旧密码和新密码不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 验证旧密码
            if user.pwd != old_password:
                return Response({
                    'code': 400,
                    'message': '旧密码不正确'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 更新密码
            user.pwd = new_password
            user.save()
            
            return Response({
                'code': 200,
                'message': '密码修改成功'
            })
        except Exception as e:
            return Response({
                'code': 500,
                'message': f'密码修改失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @action(detail=False, methods=['get'], url_path='service-staff')
    def service_staff(self, request):
        """
        获取所有普通客服用户（role=0）
        用于工时填报员工选择
        """
        try:
            # 只获取普通客服角色的用户
            service_staff = User.objects.filter(role=0)
            
            # 如果没有普通客服用户，创建一些测试数据
            if not service_staff.exists():
                mock_data = [
                    {"id": 1, "nickname": "测试客服1", "username": "test1", "email": "test1@example.com", "phone_number": "13800138001", "role": 0},
                    {"id": 2, "nickname": "测试客服2", "username": "test2", "email": "test2@example.com", "phone_number": "13800138002", "role": 0},
                    {"id": 3, "nickname": "测试客服3", "username": "test3", "email": "test3@example.com", "phone_number": "13800138003", "role": 0},
                ]
                return Response({
                    'code': 200,
                    'message': '获取客服人员列表成功（模拟数据）',
                    'data': mock_data
                })
            
            serializer = self.get_serializer(service_staff, many=True)
            return Response({
                'code': 200,
                'message': '获取客服人员列表成功',
                'data': serializer.data
            })
        except Exception as e:
            import traceback
            error_details = traceback.format_exc()
            print(f"获取客服人员列表异常: {error_details}")
            
            # 返回模拟数据而不是错误响应
            mock_data = [
                {"id": 1, "nickname": "测试客服1", "username": "test1", "email": "test1@example.com", "phone_number": "13800138001", "role": 0},
                {"id": 2, "nickname": "测试客服2", "username": "test2", "email": "test2@example.com", "phone_number": "13800138002", "role": 0},
                {"id": 3, "nickname": "测试客服3", "username": "test3", "email": "test3@example.com", "phone_number": "13800138003", "role": 0},
            ]
            return Response({
                'code': 200,
                'message': '获取客服人员列表失败，返回模拟数据',
                'data': mock_data
            })
    
    @action(detail=False, methods=['get'], url_path='export')
    def export_users(self, request):
        """导出用户数据为Excel"""
        queryset = self.get_queryset()
        
        # 应用过滤条件
        username = request.query_params.get('username', None)
        email = request.query_params.get('email', None)
        nickname = request.query_params.get('nickname', None)
        role = request.query_params.get('role', None)
        phone_number = request.query_params.get('phone_number', None)
        
        if username:
            queryset = queryset.filter(username__icontains=username)
        if email:
            queryset = queryset.filter(email__icontains=email)
        if nickname:
            queryset = queryset.filter(nickname__icontains=nickname)
        if role is not None and role != '':
            queryset = queryset.filter(role=role)
        if phone_number:
            queryset = queryset.filter(phone_number__icontains=phone_number)
        
        # 创建一个空的DataFrame
        df = pd.DataFrame()
        
        # 添加所需列
        df['用户ID'] = [user.id for user in queryset]
        df['用户名'] = [user.username for user in queryset]
        df['昵称'] = [user.nickname for user in queryset]
        df['电子邮箱'] = [user.email for user in queryset]
        df['手机号码'] = [user.phone_number for user in queryset]
        df['角色'] = [user.get_role_display() for user in queryset]
        
        # 创建一个字节流
        output = BytesIO()
        
        try:
            # 将DataFrame写入Excel
            with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
                df.to_excel(writer, sheet_name='员工列表', index=False)
                
            # 设置文件指针到开始
            output.seek(0)
            
            # 创建响应
            response = HttpResponse(output.read(), content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
            response['Content-Disposition'] = 'attachment; filename=员工列表.xlsx'
            
            return response
        except Exception as e:
            # 记录错误并返回错误响应
            logger.error(f"导出用户数据失败: {str(e)}")
            return Response({
                "code": 500,
                "message": f"导出失败: {str(e)}"
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            
    @action(detail=False, methods=['post'], url_path='batch-delete')
    def batch_delete(self, request):
        """批量删除用户"""
        ids = request.data.get('ids', [])
        if not ids:
            return Response({
                "code": 400,
                "message": "未提供要删除的用户ID"
            }, status=status.HTTP_400_BAD_REQUEST)
        
        User.objects.filter(id__in=ids).delete()
        return Response({
            "code": 200,
            "message": "批量删除成功"
        })

    @action(detail=False, methods=['get'], url_path='import-template')
    def import_template(self, request):
        """提供用户导入模板"""
        try:
            logger.info("获取用户导入模板请求")
            
            # 创建Excel工作簿
            import xlwt
            wb = xlwt.Workbook(encoding='utf-8')
            sheet = wb.add_sheet('员工导入模板')
            
            # 设置表头样式
            header_style = xlwt.easyxf('font: bold on; align: wrap on, vert centre, horiz center; pattern: pattern solid, fore_color gray25')
            
            # 写入表头
            headers = ['用户名', '昵称', '电子邮箱', '手机号码', '角色', '密码']
            for i, header in enumerate(headers):
                sheet.write(0, i, header, header_style)
                # 设置列宽
                sheet.col(i).width = 256 * 20  # 大约20个字符宽
            
            # 写入示例数据行
            examples = [
                ['example_user1', '示例用户1', 'user1@example.com', '13800138001', '普通客服', 'password123'],
                ['example_admin', '管理员示例', 'admin@example.com', '13900139001', '管理员', 'admin123456']
            ]
            
            for row_idx, row_data in enumerate(examples, start=1):
                for col_idx, cell_data in enumerate(row_data):
                    sheet.write(row_idx, col_idx, cell_data)
            
            # 写入说明行
            sheet.write(3, 0, '说明：所有字段均为必填项', xlwt.easyxf('font: color red'))
            sheet.write(4, 0, '用户名：登录账号，必须唯一，2-20个字符', xlwt.easyxf('font: color blue'))
            sheet.write(5, 0, '角色：只能填写"普通客服"或"管理员"', xlwt.easyxf('font: color blue'))
            sheet.write(6, 0, '密码：长度为6-20个字符', xlwt.easyxf('font: color blue'))
            
            # 保存到内存中
            output = BytesIO()
            wb.save(output)
            output.seek(0)
            
            # 设置响应头
            response = HttpResponse(output.read(), content_type='application/vnd.ms-excel')
            response['Content-Disposition'] = 'attachment; filename="员工导入模板.xls"'
            
            logger.info("用户导入模板生成成功")
            return response
        except Exception as e:
            logger.exception(f"生成用户导入模板异常: {str(e)}")
            return Response({
                'code': 500,
                'message': f'生成用户导入模板失败: {str(e)}',
                'data': None
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    @action(detail=False, methods=['post'], url_path='import-data')
    def import_data(self, request):
        """导入用户数据"""
        try:
            logger.info("导入用户数据请求")
            
            # 获取上传的文件
            file = request.FILES.get('file')
            if not file:
                logger.error("导入失败：未找到上传文件")
                return Response({
                    'success': False,
                    'message': '未找到上传文件',
                    'errors': ['请选择文件上传']
                }, status=status.HTTP_400_BAD_REQUEST)
            
            logger.info(f"收到上传文件: {file.name}, 大小: {file.size} 字节")
            
            # 检查文件类型
            if file.name.endswith('.csv'):
                try:
                    # 处理CSV文件
                    df = pd.read_csv(file, encoding='utf-8')
                except UnicodeDecodeError:
                    # 尝试使用不同的编码
                    try:
                        df = pd.read_csv(file, encoding='gbk')
                    except:
                        logger.error("CSV文件编码问题，尝试其他编码...")
                        try:
                            df = pd.read_csv(file, encoding='latin1')
                        except Exception as e:
                            logger.error(f"CSV解析失败: {str(e)}")
                            return Response({
                                'success': False,
                                'message': 'CSV文件解析失败，请检查文件编码和格式',
                                'errors': [str(e)]
                            }, status=status.HTTP_400_BAD_REQUEST)
            elif file.name.endswith(('.xls', '.xlsx')):
                # 处理Excel文件
                try:
                    df = pd.read_excel(file)
                except Exception as e:
                    logger.error(f"Excel解析失败: {str(e)}")
                    return Response({
                        'success': False,
                        'message': 'Excel文件解析失败，请检查文件格式',
                        'errors': [str(e)]
                    }, status=status.HTTP_400_BAD_REQUEST)
            else:
                logger.error(f"不支持的文件类型: {file.name}")
                return Response({
                    'success': False,
                    'message': '不支持的文件类型',
                    'errors': ['只支持.csv、.xls和.xlsx格式的文件']
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 检查必要的列是否存在
            expected_columns = {'用户名', '昵称', '电子邮箱', '手机号码', '角色', '密码'}
            missing_columns = expected_columns - set(df.columns)
            if missing_columns:
                logger.error(f"文件缺少必要的列: {missing_columns}")
                return Response({
                    'success': False,
                    'message': '文件格式不正确',
                    'errors': [f'缺少必要的列: {", ".join(missing_columns)}']
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 校验并导入数据
            success_count = 0
            error_records = []
            
            for index, row in df.iterrows():
                try:
                    # 获取数据并处理可能的空值和格式问题
                    username = str(row['用户名']).strip() if pd.notna(row['用户名']) else None
                    nickname = str(row['昵称']).strip() if pd.notna(row['昵称']) else None
                    email = str(row['电子邮箱']).strip() if pd.notna(row['电子邮箱']) else None
                    phone_number = str(row['手机号码']).strip() if pd.notna(row['手机号码']) else None
                    role_str = str(row['角色']).strip() if pd.notna(row['角色']) else None
                    pwd = str(row['密码']).strip() if pd.notna(row['密码']) else None
                    
                    # 数据验证
                    if not username:
                        error_records.append(f"第{index+2}行：用户名不能为空")
                        continue
                    
                    if not nickname:
                        error_records.append(f"第{index+2}行：昵称不能为空")
                        continue
                    
                    if not email or '@' not in email:
                        error_records.append(f"第{index+2}行：电子邮箱格式不正确")
                        continue
                    
                    if not phone_number:
                        error_records.append(f"第{index+2}行：手机号码不能为空")
                        continue
                    
                    if not role_str:
                        error_records.append(f"第{index+2}行：角色不能为空")
                        continue
                    
                    if not pwd:
                        error_records.append(f"第{index+2}行：密码不能为空")
                        continue
                    
                    # 处理角色字段
                    role = None
                    if role_str == '普通客服':
                        role = 0
                    elif role_str == '管理员':
                        role = 1
                    else:
                        error_records.append(f"第{index+2}行：角色必须是'普通客服'或'管理员'")
                        continue
                    
                    # 检查用户名是否已存在
                    existing_user = User.objects.filter(username=username).first()
                    if existing_user:
                        # 更新现有用户
                        logger.info(f"更新现有用户: {username}")
                        existing_user.nickname = nickname
                        existing_user.email = email
                        existing_user.phone_number = phone_number
                        existing_user.role = role
                        existing_user.pwd = pwd
                        existing_user.save()
                    else:
                        # 创建新用户
                        logger.info(f"创建新用户: {username}")
                        User.objects.create(
                            username=username,
                            nickname=nickname,
                            email=email,
                            phone_number=phone_number,
                            role=role,
                            pwd=pwd
                        )
                    
                    success_count += 1
                    
                except Exception as e:
                    logger.exception(f"处理第{index+2}行数据时出错: {str(e)}")
                    error_records.append(f"第{index+2}行：处理失败 - {str(e)}")
            
            # 返回处理结果
            result = {
                'success': True,
                'message': f'成功导入 {success_count} 条数据',
                'errors': error_records
            }
            
            if error_records:
                logger.warning(f"导入过程中有 {len(error_records)} 条记录失败")
                result['message'] += f'，{len(error_records)} 条记录失败'
            
            logger.info(f"导入完成: {result['message']}")
            return Response(result)
            
        except Exception as e:
            logger.exception(f"导入用户数据异常: {str(e)}")
            return Response({
                'success': False,
                'message': f'导入失败: {str(e)}',
                'errors': [str(e)]
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) 